﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Streambolics;

namespace MacNs
{
    public class IpToMacScanner : PayloadComputingModule
    {
        private int _Ip;
        private string _Subnet;
        private NameDatabase _Database;
        private MacToNameConverter _Converter;
        private MacFilter _Filter;

        private string _SyncMac;
        private string _SyncIp;

        public IpToMacScanner (NameDatabase aDatabase, MacToNameConverter aConverter, MacFilter aFilter)
        {
            Asynchronous = true;

            _Database = aDatabase;
            _Converter = aConverter;
            _Filter = aFilter;
        }

        public string Subnet
        {
            get
            {
                return _Subnet;
            }
            set
            {
                _Subnet = value;
                _Ip = 0;
                Delay = 1.Seconds ();
                FastReschedule = true;
            }
        }

        protected override bool InitializePayload ()
        {
            if (String.IsNullOrEmpty (_Subnet))
            {
                return false;
            }

            _Ip++;
            if (_Ip < 1 || _Ip > 254)
            {
                Delay = 5.Seconds ();
                _Ip = 1;
                FastReschedule = false;
            }

            _SyncIp = String.Format ("{0}{1}", _Subnet, _Ip);
            _SyncMac = null;

            return true;
        }

        protected override void ProcessPayload ()
        {
            _SyncMac = ArpClient.IpToMacName (_SyncIp);
        }

        protected override void PayloadError (Exception e)
        {
            _SyncMac = null;
        }

        protected override void FinalizePayload ()
        {
            if (String.IsNullOrEmpty (_SyncIp) || String.IsNullOrEmpty (_SyncMac))
            {
                return;
            }

            string Name = _Converter.Convert (_SyncMac);

            if (Name != _SyncMac)
            {
                _Database.AddMapping (_SyncIp, Name);
            }
            
            if (_Filter.Accepts (_SyncMac))
            {
                _Database.AddMapping (_SyncIp, _SyncMac);
            }
        }

        protected override void DoStart ()
        {
            DeclareStarted ();
        }

        protected override void DoStop ()
        {
            DeclareStopped ();
        }
    }
}
